package net.yegong;

import java.awt.image.BufferedImage;
import java.awt.image.Raster;
import java.io.File;
import java.util.ArrayList;
import java.util.List;

import net.yegong.gdal.GdalInfo;
import net.yegong.gdal.GdalTranslate;
import net.yegong.matrix.Matrix;

public class Reader {

	public Reader(File source, int blockSize) {
		if (blockSize < 10000) {
			throw new IllegalArgumentException("Block Size must larger than 10000");
		}
		this.blockSize = blockSize;
		this.source = source;
	}

	public void read() throws Exception {
		try {
			GdalInfo info = new GdalInfo(source);
			if (!info.isValid()) {
				throw new Exception(String.format("[%s] is not a valid image file", source.getPath()));
			}
			bands = info.getBands();
			rows = info.getRows();
			cols = info.getCols();
			GdalTranslate translate = new GdalTranslate(source);
			List<BufferedImage> images = translate.convertToBitmap();
			data = new byte[bands * rows * cols];
			int s = 0;

			List<Raster> rasters = new ArrayList<Raster>();
			for (BufferedImage i : images) {
				rasters.add(i.getData());
			}
			for (int i = 0; i < rows; ++i) {
				for (int j = 0; j < cols; ++j) {
					for (int k = 0; k < images.size(); ++k) {
						int val = rasters.get(k).getSample(j, i, 0) - 128;
						data[s++] = (byte) val;
					}
				}
			}
			index = 0;
		}
		catch (OutOfMemoryError e) {
			throw new Exception(String.format("[%s] is too big.", source.getPath()));
		}
	}

	public Matrix getNext() {
		int from = index * bands;
		if (from >= data.length) {
			return null;
		}
		index += blockSize;
		int to = index * bands;
		to = Math.min(to, data.length);
		float[] f = new float[to - from];
		for (int i = from; i < to; ++i) {
			f[i - from] = data[i];
		}
		return new Matrix(f, (to - from) / bands, bands, Matrix.C);
	}

	public byte[] getData() {
		return data;
	}

	public int getBands() {
		return bands;
	}

	public int getRows() {
		return rows;
	}

	public int getCols() {
		return cols;
	}

	private final int blockSize;
	private final File source;

	private int index;
	private byte[] data;
	private int bands;
	private int rows;
	private int cols;
}
